home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Light / poly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-20  |  33.4 KB  |  1,031 lines

  1. /**********************************************************************/
  2. /* poly.c                                                             */
  3. /*                                                                    */
  4. /* Read in polygons from and input file of format:                    */
  5. /*                                                                    */
  6. /* Number objects <number-objects>                                    */
  7. /* Object <object-id> (object-type) {                                 */
  8. /*     OWMatrix <matrix-id> { (matrix) }                              */
  9. /*     prop <property-id> { E{ vec } p{ vec } Kd{ val } Ks{ val }     */
  10. /*     NumMeshes <number-of-meshes>                                   */
  11. /*     (possible-mesh)                                                */
  12. /*                                                                    */
  13. /*  OWMatrix identifies an object to world matrix,                    */
  14. /*  prop identifies an object property, E is the emittance,           */
  15. /*  p is the reflectance, Kd = diffuse component, and Ks the specular */
  16. /*                                                                    */
  17. /* where:                                                             */
  18. /*  object-type = mesh, cube, cone, cylinder, or sphere               */
  19. /*  matrix = { vec } { vec } { vec } { vec }                          */
  20. /*  vec = val val val                                                 */
  21. /*  val = floating point value                                        */
  22. /*  possible-mesh = if (object-type == mesh) { read-mesh-in-place }   */
  23. /*                  else { mesh-read-from-file }                      */
  24. /*  mesh = Mesh <mesh-id> <number-polygons> {                         */
  25. /*            Patch vert<vertex#> <num-vertices> { vertices }         */
  26. /*            Patch norm<norm#>   <num-normals>  { normals }          */
  27. /*  vertices = { vec } { vec } ...                                    */
  28. /*  normals  = { vec } { vec } ...                                    */
  29. /*                                                                    */
  30. /* Copyright (C) 1992, Bernard Kwok                                   */
  31. /* All rights reserved.                                               */
  32. /* Revision 1.0                                                       */
  33. /* May, 1992                                                          */
  34. /**********************************************************************/
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <math.h>
  39. #include "misc.h"
  40. #include "geo.h"
  41. #include "struct.h"
  42. #include "io.h"
  43. #include "poly.h"
  44. #include "rad.h"
  45. #include "adj.h"
  46. #include "bvol.h"
  47. #include "ff.h"
  48. #include "rtime.h"
  49.  
  50. #define ENLARGE_BOX   (0.000)         /* Amount to enlarge obj BV by */
  51. #define ENLARGE_WORLD (0.6)           /* Amount to enlarge world BV by */
  52.  
  53. extern Time_Stats tstats;
  54. extern double MIN_ELEMENT_PERC;
  55. extern HBBox Scene_BVH;
  56. extern Vertex_list *vlist;
  57. extern unsigned long vlist_size;
  58. extern Vertex_tree *vtree;
  59. extern unsigned long vtree_size;
  60. extern FF_OptionType FF_Options;
  61. extern BoundingBoxType BoxCone();
  62. extern BoundingBoxType BoxCube();
  63. extern BoundingBoxType BoxCylinder();
  64. extern BoundingBoxType BoxSphere();
  65. extern void SetOptions();
  66. extern void LogStats();
  67. extern void LogRlog();
  68. extern void Create_Initial_ReceiverList();
  69. extern int test_optik;
  70. extern void Write_RadOptik();
  71.  
  72. #ifdef IRIS4D
  73. extern void InitRad();
  74. extern void DoRad();
  75. extern void CleanUpRad();
  76. #endif /* IRIS4D */
  77.  
  78. /**********************************************************************/
  79. /* Structures for reading scene */
  80. /**********************************************************************/
  81. char *tmp = "                   ";
  82. char *tmp2 = "                  ";
  83. float tmpf[9];             /* For floating pt reading only ! */
  84. int premesh = 0;
  85.  
  86. RadParams ReadLog;         /* Radiosity parameters */
  87. Scene RadScene;            /* Scene to do radiosity on */
  88.  
  89. /**********************************************************************/
  90. void Read_Prim_Mesh();
  91. void Read_Mesh();
  92. void Read_Polygon();
  93. void Read_MToW();
  94. void Read_Surface_Properties();
  95. void GetMeshFromFile();
  96. int Read_Objects();
  97. void Read_Scene();
  98. void Print_InitialStats();
  99.  
  100. /*====================================================================*/
  101. /* Polygon setup  routines */
  102. /*====================================================================*/
  103. /**********************************************************************/
  104. /* Get d paramater of plane for a polgyon                             */
  105. /**********************************************************************/
  106. double Poly_PlaneD(poly_normal, poly_point)
  107.      Vector poly_normal, poly_point;
  108. {
  109.   return(-dot(&poly_normal, &poly_point));
  110. }
  111.  
  112. /**********************************************************************/
  113. /* Get area of a n-sided polygon using Stoke's Theorem                */
  114. /**********************************************************************/
  115. double Poly_Area(v, norm, num_vert)
  116.      Vector v[MAX_PATCH_VTX];
  117.      Vector norm;
  118.      int num_vert;
  119. {
  120.   double area;
  121.   Vector v_cross_v1;
  122.   int i;
  123.   double sum_v;
  124.  
  125.   sum_v = 0.0;
  126.   for (i=0;i<num_vert;i++) {
  127.     v_cross_v1 = cross(&v[i],&v[(i+1) % num_vert]);
  128.     sum_v += dot(&norm, &v_cross_v1);
  129.   }
  130.   area = 0.5 * _ABS(sum_v);
  131.   if (area <= DAMN_SMALL)
  132.     printf("Hey the area is really small.\n");
  133.   if (area == 0.0) {
  134.     printf("Hey the area is too small.\n");
  135.     exit(1);
  136.   }
  137.   return area;
  138. }
  139.  
  140. /**********************************************************************/
  141. /* Find U, V, W planes formed by edges of quad or triangle            */
  142. /**********************************************************************/
  143. void Poly_UVW(pptr)
  144.      Polygon *pptr;
  145. {
  146.   int i;
  147.   Vector u,v,w;
  148.   Vector corner[MAX_PATCH_VTX];
  149.   polyUVW *uvw;
  150.  
  151.   uvw = (polyUVW *) malloc(sizeof(polyUVW));
  152.  
  153.   for (i=0;i<pptr->numVert;i++)
  154.     corner[i] = pptr->vert[i]->pos;
  155.  
  156.   if (pptr->class == PATCH) {
  157.     u = *vsub(&corner[1], &corner[0]);
  158.     uvw->Lu = vlen(&u);
  159.     norm(&u);
  160.     uvw->Nu = cross(&pptr->normal[0], &u);
  161.     uvw->du = Poly_PlaneD(uvw->Nu, corner[1]);
  162.     
  163.     v = *vsub(&corner[3], &corner[0]);
  164.     uvw->Lv = vlen(&v);
  165.     norm(&v);
  166.     uvw->Nv = cross(&v, &pptr->normal[0]);
  167.     uvw->dv = Poly_PlaneD(uvw->Nv, corner[3]);
  168.  
  169.   } else if (pptr->class == TRIANGLE) {
  170.     u = *vsub(&corner[1], &corner[0]);
  171.     uvw->Lu = vlen(&u);
  172.     norm(&u);
  173.     uvw->Nu = cross(&pptr->normal[0], &u);
  174.     uvw->du = Poly_PlaneD(uvw->Nu, corner[1]);
  175.  
  176.     v = *vsub(&corner[2], &corner[1]);
  177.     uvw->Lv = vlen(&v);
  178.     norm(&v);
  179.     uvw->Nv = cross(&pptr->normal[0], &v);
  180.     uvw->dv = Poly_PlaneD(uvw->Nv, corner[2]);
  181.  
  182.     w = *vsub(&corner[0], &corner[2]);
  183.     uvw->Lw = vlen(&w);
  184.     norm(&w);
  185.     uvw->Nw = cross(&pptr->normal[0], &w);
  186.     uvw->dw = Poly_PlaneD(uvw->Nw, corner[0]);
  187.  
  188.   } else {
  189.     fprintf(stderr, "Polygon type not supported. Can't calculate UVW.\n");
  190.     exit(1);
  191.   }
  192.   pptr->uvw = uvw;
  193. }
  194.  
  195.  
  196. /*====================================================================*/
  197. /* Scene reading routines                                             */
  198. /*====================================================================*/
  199.  
  200. /**********************************************************************/
  201. /* Initialize size of world */
  202. /**********************************************************************/
  203. void Init_WorldSize(rlog)
  204.      RadParams *rlog;
  205. {
  206.   rlog->worldbox.min.x = VERY_LARGE / 2.0;
  207.   rlog->worldbox.min.y = VERY_LARGE / 2.0;
  208.   rlog->worldbox.min.z = VERY_LARGE / 2.0;
  209.   rlog->worldbox.max.x = -VERY_LARGE / 2.0;
  210.   rlog->worldbox.max.y = -VERY_LARGE / 2.0;
  211.   rlog->worldbox.max.z = -VERY_LARGE / 2.0;
  212.   rlog->worldSize = VERY_LARGE / 2.0;
  213. }
  214.  
  215. /**********************************************************************/
  216. /* Find minumum bounding box size for the world */
  217. /**********************************************************************/
  218. void Update_WorldSize(pt)
  219.      Vector pt;
  220. {
  221.   if (pt.x > ReadLog.worldbox.max.x)  ReadLog.worldbox.max.x = pt.x;
  222.   if (pt.y > ReadLog.worldbox.max.y)  ReadLog.worldbox.max.y = pt.y;
  223.   if (pt.z > ReadLog.worldbox.max.z)  ReadLog.worldbox.max.z = pt.z;
  224.  
  225.   if (pt.x < ReadLog.worldbox.min.x)  ReadLog.worldbox.min.x = pt.x;
  226.   if (pt.y < ReadLog.worldbox.min.y)  ReadLog.worldbox.min.y = pt.y;
  227.   if (pt.z < ReadLog.worldbox.min.z)  ReadLog.worldbox.min.z = pt.z;
  228. }
  229.  
  230. /**********************************************************************/
  231. /* Make bounding sphere and bounding box of world */
  232. /**********************************************************************/
  233. void BoxWorld(rlog)
  234.      RadParams *rlog;
  235. {
  236.   if (rlog->worldbox.min.x > rlog->worldbox.max.x) {
  237.     printf("Oh oh. the world min is greater than the max!\n");
  238.     exit(1);
  239.   }
  240.   rlog->worldbox.min.x -= ENLARGE_WORLD;
  241.   rlog->worldbox.min.y -= ENLARGE_WORLD;
  242.   rlog->worldbox.min.z -= ENLARGE_WORLD;
  243.   rlog->worldbox.max.x += ENLARGE_WORLD;
  244.   rlog->worldbox.max.y += ENLARGE_WORLD;
  245.   rlog->worldbox.max.z += ENLARGE_WORLD;
  246.  
  247.   rlog->worldSize = 0.5 * (vdist(&(rlog->worldbox.max), 
  248.                  &(rlog->worldbox.min)) + 0.5);
  249. }
  250.  
  251. /**********************************************************************/
  252. /* Make bounding sphere and bounding box of world */
  253. /**********************************************************************/
  254. void Enlarge_BoxSize(box)
  255.      BoundingBoxType *box;
  256. {
  257.   box->min.x -= ENLARGE_BOX;
  258.   box->min.y -= ENLARGE_BOX;
  259.   box->min.z -= ENLARGE_BOX;
  260.   box->max.x += ENLARGE_BOX;
  261.   box->max.y += ENLARGE_BOX;
  262.   box->max.z += ENLARGE_BOX;
  263. }
  264.  
  265. /**********************************************************************/
  266. /* Subdivide patches into elements before performing radiosity comp.  */
  267. /**********************************************************************/
  268. void Presub_Polygon(pptr, level)
  269.      Polygon *pptr;
  270.      int level;
  271. {
  272.   int i;
  273.  
  274.   if (level <= 0) return;
  275.   else {
  276.     Subdivide_Polygon(pptr);
  277.     level--;
  278.     for (i=0;i<MAX_PATCH_CHILDREN;i++) 
  279.       Presub_Polygon(pptr->child[i], level);
  280.   }
  281. }
  282.  
  283. /**********************************************************************/
  284. /* Read in polygon info */
  285. /**********************************************************************/
  286. void Read_Polygon(meshf, pptr, mptr, optr, origB)
  287.      FILE *meshf;
  288.      Polygon *pptr;
  289.      Mesh *mptr;
  290.      Objectt *optr;
  291.      Spectra origB;
  292. {
  293.   int i,j;
  294.   float tmpf[4];
  295.   char *tmp = "                    ";
  296.   Vector va[MAX_PATCH_VTX];
  297.   Vector v;
  298.  
  299.   /* Read in name and number of normals for the patch */
  300.   fscanf(meshf,"%s %d {",tmp , &(pptr->numVert));
  301.   pptr->id = ReadLog.totpoly++;
  302.   pptr->next = pptr+1;
  303.   if (Option.debug) printf("  Patch %s %d {", tmp, pptr->numVert);
  304.   
  305.   /* Set id, type, no children, tree level, mesh poly belongs to,
  306.    and poly, this poly belongs to */
  307.   if (pptr->numVert == 4) {
  308.     pptr->name = PATCH_ID;
  309.     pptr->class = PATCH;
  310.   } else if (pptr->numVert == 3) {
  311.     pptr->name = TRI_ID;
  312.     pptr->class = TRIANGLE;
  313.   } else {
  314.     fprintf(stderr, "Sorry, only quadtralaterals and triangles allowed\n");
  315.     exit(1);
  316.   }
  317.   for(i=0;i<MAX_PATCH_CHILDREN;i++)
  318.     pptr->child[i] = 0;               /* No children yet */
  319.   pptr->level = 0; pptr->Pfather = 0; /* is root of quad-tri tree */
  320.   pptr->Mfather = mptr;               /* mesh poly belongs to */
  321.   pptr->Links = (PolyList *)0;        /* No form factor links */
  322.   pptr->polyhead.front = pptr->polyhead.back = pptr->Links;
  323.   pptr->polyhead.num_polys = 0;
  324.     
  325.   /* Set total and unshot radiosity values for patch, and vertices */
  326.   for(i=0;i<MAX_SPECTRA_SAMPLES;i++) {
  327.     pptr->unshot_B.samples[i] = pptr->B.samples[i] = origB.samples[i];
  328.     for (j=0;j<pptr->numVert;j++)
  329.       pptr->vtx_B[j].samples[i] = origB.samples[i];
  330.   }
  331.   
  332.   /* Read normals of patch */
  333.   for (i=0;i<(pptr->numVert);i++) {
  334.     fscanf(meshf, " { %g %g %g }", &tmpf[0], &tmpf[1], &tmpf[2]);
  335.     pptr->normal[i].x = tmpf[0];
  336.     pptr->normal[i].y = tmpf[1];
  337.     pptr->normal[i].z = tmpf[2];
  338.     norm(&(pptr->normal[i]));
  339.  
  340.     /* Rotate normals if needed into world space */
  341.     if (same_matrix3x3(optr->MToW, Identity) == 0) {
  342.       pptr->normal[i] = vrotate(pptr->normal[i], optr->MToW);
  343.       norm(&(pptr->normal[i]));
  344.     }
  345.     
  346.     if (Option.debug)
  347.       printf(" { %g %g %g }", (pptr->normal[i].x),
  348.          (pptr->normal[i].y),(pptr->normal[i].z));
  349.   }
  350.   fscanf(meshf," }\n"); /* End normal read */
  351.   if (Option.debug) printf(" }\n");
  352.  
  353.   /* Read in size = number of vertices of patch */
  354.   fscanf(meshf, "Patch %s %d {", tmp, &(pptr->numVert));
  355.   if (Option.debug) printf("  Patch %s %d {", tmp, pptr->numVert);
  356.  
  357.   /* Read vertices of patch */
  358.   for (i=0;i<(pptr->numVert);i++) {
  359.     fscanf(meshf, " { %g %g %g }", &tmpf[0], &tmpf[1], &tmpf[2]);
  360.     v.x = tmpf[0]; 
  361.     v.y = tmpf[1]; 
  362.     v.z = tmpf[2];
  363.  
  364.     /* Transform vertex if needed into world space */
  365.     if (same_matrix(optr->MToW, Identity) == 0)
  366.       v = vtransform(v, optr->MToW);
  367.     if (Option.debug) printf(" {%g %g %g}", v.x, v.y, v.z);
  368.     va[i] = v;
  369.  
  370.     /* Update size of the world, and size of bounding box for mesh */
  371.     Update_WorldSize(v);
  372.     if (optr->num_meshes != -1)       /* Is not a primitive */
  373.       Update_BoxSize(v,optr->box);
  374.     if (optr->primid == MESH) 
  375.       Update_BoxSize(v,mptr->box);
  376.  
  377.     /* Form adjacency links between vertices and polygon */
  378.     if (vtree == 0) { /* Empty vertex tree */
  379.       pptr->vert[i] = Vertex_Create(v,pptr);
  380.       vtree = VTree_NodeCreate(pptr->vert[i],0); /* No father, is root */
  381.     } else {
  382.       VTree_NodeFind(v,vtree,pptr,i);
  383.     }
  384.   
  385.   }
  386.   fscanf(meshf," }\n"); /* End polygon vertex read */
  387.   if (Option.debug) printf(" }\n");
  388.  
  389.   /* Calculate area and d of plane where poly resides */  
  390.   pptr->d = Poly_PlaneD(pptr->normal[1], va[1]);
  391.   pptr->area = Poly_Area(va, pptr->normal[0], pptr->numVert);
  392.  
  393.   /* Calculate u,v,w planes of edges of poly */
  394.   Poly_UVW(pptr);
  395.   pptr->changingNormal = 0;
  396.  
  397.   /* Calculate total energy and total area in scene */
  398.   ReadLog.totalArea += pptr->area;
  399.   for(i=0;i<MAX_SPECTRA_SAMPLES;i++)
  400.     ReadLog.totalEnergy += origB.samples[i] * pptr->area;
  401.  
  402.   /* Pre-subdivide if specified */
  403.   if (premesh == 1) 
  404.     Subdivide_Polygon(pptr);
  405.   else if (premesh > 1) 
  406.     Presub_Polygon(pptr, premesh);
  407. }
  408.  
  409. /**********************************************************************/
  410. /* Read mesh info */
  411. /**********************************************************************/
  412. void Read_Mesh(meshf, optr)
  413.      FILE *meshf;
  414.      Objectt *optr;
  415. {
  416.   Mesh *mptr;
  417.   Polygon *pptr;
  418.   char *tmp = "                    ";
  419.  
  420.   if (Option.debug) printf("  NumMeshes %d\n", optr->num_meshes);
  421.   mptr = optr->meshes
  422.     = (Mesh *)malloc ((optr->num_meshes) *sizeof(Mesh));
  423.   ReadLog.meshcount = 0;
  424.  
  425.   /* Read in mesh information from current input file */
  426.   while ((fscanf(meshf,"    Mesh ") != -1) && 
  427.      (ReadLog.meshcount < optr->num_meshes)) {
  428.  
  429.     /* Allocate space for polygons in mesh */
  430.     fscanf(meshf, "%s %d {\n", tmp, &(mptr->num_polys));
  431.     mptr->id = ReadLog.totmesh++;
  432.     mptr->name = MESH_ID;
  433.     mptr->Ofather = optr;
  434.     pptr = mptr->polys
  435.       = (Polygon *)malloc ((mptr->num_polys) *sizeof(Polygon));
  436.  
  437.     /* Allocate space for mesh bounding box if object is 
  438.        a polygonal mesh */
  439.     if (optr->primid == MESH) {
  440.       mptr->box = (BoundingBoxType *) malloc(sizeof(BoundingBoxType));
  441.       BoxInit(mptr->box);
  442.     } else 
  443.       mptr->box = (BoundingBoxType *)0;
  444.  
  445.     if (Option.debug) printf("  Mesh %s %d {\n", tmp, mptr->num_polys);
  446.     
  447.     /* Read in polygon information for mesh */
  448.     ReadLog.polycount = 0;
  449.     while ((fscanf(meshf,"    Patch ") != -1) && 
  450.        (ReadLog.polycount < mptr->num_polys)) {
  451.       
  452.       Read_Polygon(meshf,pptr,mptr,optr,optr->surface->rad.E);
  453.       pptr++;
  454.       ReadLog.polycount++;
  455.     }
  456.     fscanf(meshf,"    }\n"); /* End mesh read */
  457.  
  458.     mptr++;
  459.     ReadLog.meshcount++;
  460.   }
  461. }
  462.  
  463. /**********************************************************************/
  464. /* Read object to world space matrix, and create inverse matrix */
  465. /**********************************************************************/
  466. void Read_MToW(meshf, optr)
  467.      FILE *meshf;
  468.      Objectt *optr;
  469. {
  470.   int i,j;
  471.  
  472.   /* Read in object to world matrix, and set world-object matrix */
  473.   fscanf(meshf,"OWMatrix %s { ", tmp);
  474.   copy_matrix(Identity, optr->MToW);
  475.   for (i=0; i<4; i++) for (j=0; j<3; j++) {
  476.     fscanf(meshf,"%g ", &tmpf[0]);
  477.     optr->MToW[i][j] = tmpf[0];
  478.   }
  479.   invert_matrix(optr->MToW,optr->WToM);
  480.   fscanf(meshf,"}\n"); /* End read matrix */
  481.           
  482.   if (Option.debug) {
  483.     printf("  OWMatrix %s {\n", tmp);
  484.     for(i=0;i<4;i++) {
  485.       printf("\t");
  486.       for(j=0;j<4;j++) printf("%g ", optr->MToW[i][j]);
  487.       printf("\n");
  488.     }
  489.   }
  490. }
  491.  
  492. /**********************************************************************/
  493. /* Allocate space and read in object surface properties */
  494. /**********************************************************************/
  495. void Read_Surface_Properties(meshf, optr)
  496.      FILE *meshf;
  497.      Objectt *optr;
  498.   SurfaceProp *sptr;
  499.   static int surfprop_id = 0;
  500.  
  501.   /* Allocate space for surface properties */
  502.   sptr = optr->surface = (SurfaceProp *)malloc(sizeof(SurfaceProp));    
  503.    
  504.   fscanf(meshf,
  505.      "    Prop %s { E{ %g %g %g } p{ %g %g %g } Kd{ %g } Ks{ %g } }\n",
  506.      tmp, &tmpf[0], &tmpf[1], &tmpf[2], &tmpf[3], &tmpf[4], &tmpf[5],
  507.      &tmpf[6], &tmpf[7]);
  508.   sptr->id = surfprop_id++;
  509.   sptr->name = tmp;
  510.   sptr->rad.E.samples[0] = tmpf[0];    /* Emittance */
  511.   sptr->rad.E.samples[1] = tmpf[1]; 
  512.   sptr->rad.E.samples[2] = tmpf[2];
  513.   sptr->shade.p.samples[0] = tmpf[3];  /* Reflectance */
  514.   sptr->shade.p.samples[1] = tmpf[4];
  515.   sptr->shade.p.samples[2] = tmpf[5];
  516.   sptr->shade.Kd.samples[0] = tmpf[6]; /* Diffuse & specular coefficients */
  517.   sptr->shade.Ks.samples[0] = tmpf[7];
  518.   sptr->rad.B.samples[0] = 0.0;        /* Radiance */
  519.   sptr->rad.B.samples[1] = 0.0;
  520.   sptr->rad.B.samples[2] = 0.0;
  521.  
  522.   if (Option.debug) 
  523.     printf("  Prop %s { E{ %g %g %g } p{ %g %g %g } Kd{ %g } Ks{ %g } }\n",
  524.        tmp, sptr->rad.E.samples[0],
  525.        sptr->rad.E.samples[1], sptr->rad.E.samples[2],
  526.        sptr->shade.p.samples[0], sptr->shade.p.samples[1], 
  527.        sptr->shade.p.samples[2], 
  528.        sptr->shade.Kd.samples[0], sptr->shade.Ks.samples[0]);
  529. }
  530.  
  531. /**********************************************************************/
  532. /* Read in mesh from primitive mesh file */
  533. /**********************************************************************/
  534. void Read_Prim_Mesh(filename, optr)
  535.      char *filename;
  536.      Objectt *optr;
  537. {
  538.   static int var_set = 0;
  539.   static char *path = "                                        ";
  540.   char *tmp = "                                                  ";
  541.   
  542.   if (!var_set) {
  543.     if ((path = getenv("PR_prims")) != NULL) {
  544.       var_set = 1;
  545.     } else {
  546.       fprintf(stderr,"%s: Please set environment variable PR_prims to specify\n\t path where meshed primitives may be found first. Then rerun\n", ProgName);
  547.       exit(0);
  548.     }
  549.   }
  550.   sprintf(tmp,"%s/%s", path, filename); filename = tmp;
  551.   /* printf("filename = %s\n", tmp); */
  552.  
  553.   if (!(pmesh = fopen(filename, "r"))) {
  554.     fprintf(stderr,"%s: cannot read object file %s\n", ProgName, filename);
  555.     exit(1);
  556.   }
  557.  
  558.   fscanf(pmesh, "NumMeshes %d\n", &(optr->num_meshes));
  559.   ReadLog.polycount = 0;
  560.   Read_Mesh(pmesh, optr);
  561.   fclose(pmesh);
  562. }
  563.  
  564. /**********************************************************************/
  565. /* Read in scene from a input file */
  566. /**********************************************************************/
  567. void GetMeshFromFile(objtype, optr)
  568.      char *objtype;
  569.      Objectt *optr;
  570. {
  571.   BoundingBoxType obox;
  572.  
  573.   optr->primtype = objtype;
  574.  
  575.   /* Check if normals facing in or out */
  576.   if (optr->num_meshes == -2) 
  577.     optr->in_facingprim = TRUE;
  578.   else
  579.     optr->in_facingprim = FALSE;
  580.  
  581.   if (strcmp(objtype,"cone") == 0) {
  582.     obox = BoxCone();
  583.     optr->primid = CONE;
  584.     if (optr->num_meshes == -2) {
  585.       if (ReadLog.log) printf("\t*** cone(in) reading...\n");
  586.       Read_Prim_Mesh(iconefilename, optr);
  587.     } else {
  588.       if (ReadLog.log) printf("\t*** cone(out) reading...\n");
  589.       Read_Prim_Mesh(conefilename, optr);
  590.     }
  591.   } else if (strcmp(objtype,"cube") == 0) {
  592.     obox = BoxCube();
  593.     optr->primid = CUBE;
  594.     if (optr->num_meshes == -2) {
  595.       if (ReadLog.log) printf("\t*** cube(in) reading...\n");
  596.       Read_Prim_Mesh(icubefilename, optr);
  597.     } else {
  598.       if (ReadLog.log) printf("\t*** cube(out) reading...\n");
  599.       Read_Prim_Mesh(cubefilename, optr);
  600.     }
  601.   } else if (strcmp(objtype,"cylinder") == 0) {
  602.     obox = BoxCylinder();
  603.     optr->primid = CYLINDER;
  604.     if (optr->num_meshes == -2) {
  605.       if (ReadLog.log) printf("\t*** cylinder(in) reading...\n");
  606.       Read_Prim_Mesh(icylfilename, optr);
  607.     } else {
  608.       if (ReadLog.log) printf("\t*** cylinder(out) reading...\n");
  609.       Read_Prim_Mesh(cylfilename, optr);
  610.     }
  611.   } else if (strcmp(objtype,"sphere") == 0) {
  612.     obox = BoxSphere();
  613.     optr->primid = SPHERE;
  614.     if (optr->num_meshes == -2) {
  615.       if (ReadLog.log) printf("\t*** sphere(in) reading...\n");
  616.       Read_Prim_Mesh(isphfilename, optr);
  617.     } else {
  618.       if (ReadLog.log) printf("\t*** sphere(out) reading...\n");
  619.       Read_Prim_Mesh(sphfilename, optr);
  620.     }
  621.   } else {
  622.     printf("There's something wrong, primitive is invalid\n");
  623.     exit(0);
  624.   }
  625.   /* optr->num_meshes = -1; */
  626.  
  627.   /* Get transformed bounding box for object if tranformation 
  628.      not Identity */
  629.   if (same_matrix3x3(optr->MToW, Identity) == 0)
  630.     Bounds_Transform(optr->MToW, obox, optr->box);
  631.   Option.debug = 0;
  632. }
  633.  
  634. char *objmatch[5] = 
  635.   "precone", "precube", "precylinder", "premesh", "presphere" 
  636. };
  637. char *objreal[5] = 
  638.   "cone", "cube", "cylinder", "mesh", "sphere" 
  639. };
  640. /**********************************************************************/
  641. /* Search string a for b, and return first number found               */
  642. /**********************************************************************/
  643. int Check_premesh(a, realtype)
  644.      char *a, **realtype;
  645. {
  646.   int match = 0;          /* Match found */
  647.   char level[2];          /* level to subdivide to */
  648.   int i;
  649.  
  650.   i=0;
  651.   while (i<5 && !match)   /* Scan for object type, return type */
  652.     if (strstr(a,objmatch[i])) {
  653.       match = 1;
  654.       *realtype = objreal[i];
  655.     }
  656.     else i++;
  657.  
  658.   if (match)              /* Scan for number of levels to mesh to */
  659.     for (i=0;i<9;i++) {
  660.       sprintf(level, "%d", i+1);
  661.       if (strstr(a, level))
  662.     match = i+1;
  663.     }
  664.   return(match);
  665. }
  666.  
  667. /**********************************************************************/
  668. /* Read in objects from file */
  669. /**********************************************************************/
  670. int Read_Objects(filename, obj)
  671.      char *filename;
  672.      Objectt **obj;     
  673. {
  674.   int nobjs = 0;                  /* Number of objects to read */
  675.   Objectt *optr;
  676.  
  677.   if (!(meshf = fopen(filename, "r"))) {
  678.     fprintf(stderr,"%s: cannot read object file %s\n", ProgName, filename);
  679.     exit(1);
  680.   }
  681.  
  682.   /* Find out # of objects and allocate space */
  683.   fscanf(meshf,"Number objects %d\n", &nobjs);
  684.   if (Option.debug) printf("Number objects %d\n", nobjs);
  685.   optr = *obj = (Objectt *)malloc (nobjs *sizeof(Objectt));
  686.  
  687.   /* Scan for objects (id, object type) */
  688.   ReadLog.objcount = 0;
  689.   while ((fscanf(meshf,"Object") != -1) && (ReadLog.objcount < nobjs)) {
  690.  
  691.     /* Set id, name, and primitive type */
  692.     fscanf(meshf, "%s %s {\n", tmp, tmp2);
  693.     optr->id = ReadLog.objcount;
  694.     optr->rayID = -1;
  695.     optr->name = "object"; 
  696.     optr->primtype = tmp2;
  697.  
  698.     if (premesh = Check_premesh(tmp2,&optr->primtype))
  699.       printf("\t    Tesselating %s (%d) to level %d\n", 
  700.          optr->primtype, optr->id, premesh);
  701.  
  702.     if (Option.debug)
  703.       printf("Object%d %s %s {\n", optr->id, optr->name, optr->primtype);
  704.  
  705.     /* Allocate space for object bounding volume */
  706.     optr->box = (BoundingBoxType *) malloc(sizeof(BoundingBoxType));
  707.  
  708.     /* Read model to world matrix */
  709.     Read_MToW(meshf, optr);
  710.  
  711.     /* Read surface properties */
  712.     Read_Surface_Properties(meshf, optr);
  713.       
  714.     /* Find out number of meshes in object */
  715.     fscanf(meshf, "    NumMeshes %d\n", &(optr->num_meshes));
  716.  
  717.     if ((optr->num_meshes) == -1 || (optr->num_meshes) == -2) {
  718.       /* Read in mesh info from primitive-mesh input files */
  719.       /* depending on type of object */
  720.       GetMeshFromFile(optr->primtype,optr); 
  721.  
  722.     } else {
  723.       /* Reading in mesh info from current input file */
  724.       if (ReadLog.log) printf("\t*** mesh reading...\n");
  725.       optr->primid = MESH;
  726.       BoxInit(optr->box);
  727.       Read_Mesh(meshf, optr);
  728.     }
  729.     fscanf(meshf,"}\n"); /* End object read */
  730.     if (Option.debug) printf("}\n");
  731.  
  732.     /* Enlarge box around object just a bit ? */
  733.     /* Enlarge_BoxSize(optr->box); */
  734.     
  735.     optr++;
  736.     ReadLog.objcount++;
  737.   }
  738.  
  739.   ReadLog.totalEnergyLeft = ReadLog.totalEnergy;
  740.   fclose(meshf);
  741.   return(ReadLog.objcount);
  742. }
  743.  
  744. /**********************************************************************/
  745. /* Read in textures from file (not implemented)                       */
  746. /**********************************************************************/
  747. int Read_Textures(filename, tex)
  748.      char *filename;
  749.      TextureProp **tex;     
  750. {
  751.   if (!(textf = fopen(filename, "r"))) {
  752.     fprintf(stderr,"%s: cannot read texture file %s\n", ProgName, filename);
  753.     exit(1);
  754.   }
  755.   printf("Not implemented yet...sorry no textures\n");
  756.   return 0;
  757. }
  758.  
  759. /**********************************************************************/
  760. /* Print element / receiver list */
  761. /**********************************************************************/
  762. void Print_Elements(elist,elist_size)
  763.      Elist *elist;
  764.      int elist_size;
  765. {
  766.   int i;
  767.   Elist *elptr;
  768.  
  769.   elptr = elist;
  770.   for(i=0;i<elist_size;i++,elptr=elptr->next)
  771.     printf("\tElement %s%d, ff %g, is %sa receiver\n",
  772.        elptr->element->name, elptr->element->id,
  773.        elptr->ff, (elptr->is_receiver == 1 ? "" : "not "));
  774. }
  775.  
  776. /**********************************************************************/
  777. /* Print program options, and statistics */
  778. /**********************************************************************/
  779. void Print_InitialStats(rlog,fp)
  780.      RadParams rlog;
  781.      FILE *fp;
  782. {
  783.   if (rlog.log) {
  784.     fprintf(fp,"\n\t*** Scene statistics ***\n");
  785.     fprintf(fp,"\tTotal objects read: %d\n", rlog.objcount);
  786.     fprintf(fp,"\tTotal meshes read: %d\n", rlog.totmesh);
  787.     fprintf(fp,"\tTotal polygons read: %d\n", rlog.totpoly);
  788.     fprintf(fp,"\tTotal vertices read to octree: %d\n", vtree_size);
  789.     fprintf(fp,"\tTotal textures read: %d\n", rlog.num_textures);
  790.     fprintf(fp,"\n");
  791.     /* if (ReadLog.num_elements > 0) {
  792.        fprintf(fp,"\tTotal elements read: %d\n", rlog.num_elements);
  793.        Print_Elements(rlog.elements, rlog.num_elements);
  794.        fprintf(fp,"\tTotal receivers: %d\n", rlog.num_receivers);
  795.        } */
  796.     fprintf(fp,"\tStopping threshold: %g and iterations: %d\n", rlog.threshold,
  797.        rlog.max_iterations);
  798.     fprintf(fp,"\tIntensity scale for display: %g\n", rlog.intensityScale);
  799.     /* if (Option.ambient)
  800.        fprintf(fp,"\tInitial ambient term: (%g %g %g)\n", 
  801.        rlog.ambient_term.samples[0], rlog.ambient_term.samples[1],
  802.        rlog.ambient_term.samples[2]);
  803.        */
  804.     fprintf(fp,"\tThe worlds radius is: %g\n", rlog.worldSize);
  805.     fprintf(fp,"\t\twith min-point %g,%g,%g\n\t\tand max-point %g,%g,%g\n",
  806.        rlog.worldbox.min.x, rlog.worldbox.min.y, rlog.worldbox.min.z, 
  807.        rlog.worldbox.max.x, rlog.worldbox.max.y, rlog.worldbox.max.z);
  808.     fprintf(fp,"\t\thas a total energy of: %g\n", rlog.totalEnergy);
  809.     fprintf(fp,"\t\tand has a total area of: %g\n", rlog.totalArea);
  810.  
  811.     ff_print_FF_Options(FF_Options);
  812.     if (Option.ff_raytrace == 0) {
  813.       fprintf(fp,"\tUsing hemicube visibility testing, with\n");
  814.       fprintf(fp,"\ttop resolution of %d\n", rlog.hemicubeRes);
  815.     } else {
  816.       if (FF_Options.quadtri_ray) 
  817.     fprintf(fp,"\tUsing Ray-QuadTri intersection test.\n");
  818.       else
  819.     fprintf(fp,"\tUsing Ray-General Polygon intersection test.\n");
  820.       if (Option.grid)
  821.     fprintf(fp,"\tUsing hierarchical bounding volumes\n");
  822.       if (FF_Options.shaft_cull) 
  823.     fprintf(fp,"\tUsing source/receiver shaft culling\n");
  824.       else {
  825.     if (FF_Options.src_rec_cull) 
  826.       fprintf(fp,"\tUsing source and receiver plane culling.\n");
  827.     else
  828.       fprintf(fp,"\tUsing source plane culling.\n");
  829.       }
  830.     }
  831.     fprintf(fp,"\n");
  832.   }
  833. }
  834.  
  835. /**********************************************************************/
  836. /* Read in the scene (s) from file */
  837. /**********************************************************************/
  838. void Read_Scene(s)
  839.      Scene *s;
  840. {
  841.   printf("\n\t*** Reading scene from %s ***\n",Option.meshfilename);
  842.  
  843.   /* Initialize size of the world */
  844.   Init_WorldSize(&ReadLog);
  845.  
  846.   /* Create vertex octree */
  847.   /* vtree = VTree_Create(ReadLog); */
  848.  
  849.   /* Read in objects and textures */
  850.   s->num_objects = Read_Objects(Option.meshfilename, &(s->objects));
  851.   /*  s->num_textures = Read_Textures(Option.textfilename, &(s->textures)); */
  852.  
  853.   /* Read in viewing parameters */
  854.   printf("\n\t*** Reading view from %s ***\n", Option.viewfilename);
  855.   Read_View(Option.viewfilename,&(ReadLog.displayView));
  856.  
  857.   /* Calculate minimum  world size */
  858.   BoxWorld(&ReadLog);
  859.  
  860.   /* Set minimum element area */
  861.   FF_Options.min_element_area = (MIN_ELEMENT_PERC * ReadLog.totalArea / 
  862.                  (double) ReadLog.totpoly);
  863. }
  864.  
  865. /**********************************************************************/
  866. /* Read in a view */
  867. /**********************************************************************/
  868. void Read_View(filename,c)
  869.      char *filename;
  870.      Camera *c;
  871. {
  872.   float t[3];
  873.   int t1, t2;
  874.  
  875.   if (!(viewf = fopen(filename, "r"))) {
  876.     fprintf(stderr,"\t%s: cannot read view file %s\n", ProgName, filename);
  877.     fprintf(stderr,"\tSetting to default viewing parameters\n");
  878.     c->lookfrom.x = ReadLog.worldbox.max.x - 2.*ENLARGE_WORLD;
  879.     c->lookfrom.y = ReadLog.worldbox.max.y - 2.*ENLARGE_WORLD;
  880.     c->lookfrom.z = ReadLog.worldbox.max.z - 2.*ENLARGE_WORLD;
  881.     c->lookat.x = (ReadLog.worldbox.max.x - ReadLog.worldbox.min.x ) / 2.0;
  882.     c->lookat.y = (ReadLog.worldbox.max.y - ReadLog.worldbox.min.y ) / 2.0;
  883.     c->lookat.z = (ReadLog.worldbox.max.z - ReadLog.worldbox.min.z ) / 2.0;
  884.     c->lookup.x = 0.;    c->lookup.y = 1.;       c->lookup.z = 0.;
  885.     c->fovx = 60;   c->fovy = 60;
  886.     c->near = 0.001; c->far = ReadLog.worldSize;
  887.     c->xRes = 256; c->yRes = 256;
  888.     c->bank = 0.0;
  889.  
  890.   } else {
  891.     fscanf(viewf,"Camera {\n");
  892.  
  893.     fscanf(viewf,"lookfrom %g %g %g\n", &t[0], &t[1], &t[2]);
  894.     c->lookfrom.x = t[0];
  895.     c->lookfrom.y = t[1];
  896.     c->lookfrom.z = t[2];
  897.     
  898.     fscanf(viewf,"lookat %g %g %g\n", &t[0], &t[1], &t[2]);
  899.     c->lookat.x = t[0];
  900.     c->lookat.y = t[1];
  901.     c->lookat.z = t[2];
  902.     
  903.     fscanf(viewf,"lookup %g %g %g\n", &t[0], &t[1], &t[2]);
  904.     c->lookup.x = t[0];
  905.     c->lookup.y = t[1];
  906.     c->lookup.z = t[2];
  907.     
  908.     fscanf(viewf,"fovx %d fovy %d near %g far %g\n", &t1, &t2, &t[0], &t[1]);
  909.     c->fovx = t1;   c->fovy = t2;
  910.     c->near = t[0]; c->far = t[1];
  911.     fscanf(viewf,"xRes %d yRes %d\n", &t1, &t2);
  912.     c->xRes = t1; c->yRes = t2;
  913.     fscanf(viewf,"bank %g\n", &t[0]);
  914.     c->bank = t[0];
  915.     fscanf(viewf,"}");
  916.   }
  917.  
  918.   /* Allocate buffer for display purposes -- not used */
  919.   c->buffer = (unsigned  long *)0;
  920.   /* malloc(ReadLog.displayView.xRes * ReadLog.displayView.yRes *
  921.      sizeof(unsigned long)); */
  922. }
  923.  
  924. extern int p_count;
  925. /**********************************************************************/
  926. /* Main program */
  927. /**********************************************************************/
  928. void main(argc, argv)
  929.      int argc;
  930.      char *argv[];
  931. {
  932.   int temp;
  933.   float prep_start, prep_end;
  934.   float tot_start, tot_end;
  935.   char *env_var = "                                                  ";
  936.  
  937.   /* Set up options */
  938.   SetOptions(argc, argv);
  939.   Init_Time();
  940.  
  941.   /* Open table log */
  942.   if ((env_var = getenv("PR_run")) != NULL) {
  943.     Option.tablelogstr = env_var;  
  944.     Option.tablelog = TRUE;
  945.     LogRlog(1,Option.meshfilename,Option.tablelogstr);
  946.   } else 
  947.     Option.tablelog = FALSE;
  948.  
  949.   /* Read the scene in */
  950.   temp = Option.debug; Option.debug = 0;  
  951.  
  952.   if (Option.statistics)
  953.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  954.  
  955.   Read_Scene(&RadScene);
  956.  
  957.   if (Option.statistics) {
  958.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  959.     tstats.prep_Model = (prep_end - prep_start);
  960.   }
  961.  
  962.   if (Option.statistics)
  963.     if (Option.device == PRINT) Print_InitialStats(ReadLog,stdout);
  964.     else Print_InitialStats(ReadLog,Option.StatFile);
  965.   if (Option.print_scene) print_Scene(&RadScene,Option.InLogFilename);
  966.   Option.debug = temp;
  967.  
  968.   /* Build hierarchical bounding volume tree for scene */
  969.   if (Option.grid) { 
  970.  
  971.     /* Build object HBV */
  972.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  973.  
  974.     BVH_Create_Hierarchy(&RadScene, &Scene_BVH);
  975.  
  976.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  977.     tstats.prep_oHBV = (prep_end - prep_start);
  978.     tstats.tot_time += tstats.prep_oHBV;
  979.  
  980.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  981.     
  982.     /* Build polygon HBV */
  983.     BVH_Create_PHierarchy(&Scene_BVH);
  984.     /* printf("\t%d Polygons added to tree.\n", p_count); */
  985.     Enlarge_Root();
  986.  
  987.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  988.     tstats.prep_pHBV = (prep_end - prep_start);
  989.     tstats.tot_time += tstats.prep_pHBV;
  990.  
  991.     if (Option.debug) {
  992.       printf("\t*** Hierarchical BV tree ***\n");
  993.       temp = Option.debug;
  994.       Option.debug = 0;
  995.       BVH_PrintBox(&Scene_BVH);
  996.       BVH_PrintHier(&Scene_BVH);
  997.       printf("\n");
  998.       Option.debug = temp;
  999.     }
  1000.   }
  1001.  
  1002.   /* Run radiosity on the scene */
  1003.   Init_Rad(&RadScene);
  1004.   Do_Rad();
  1005.  
  1006.   /* Perform cleanup */
  1007.   /* CleanUp_Rad(); */
  1008.   if (Option.statistics)
  1009.     if (Option.device == FILES)
  1010.       LogStats(0);
  1011.  
  1012.   /* Log scene with radiosity calculated */
  1013.   if (Option.print_scene) print_Scene(&RadScene, Option.OutLogFilename);
  1014.  
  1015.   /* Output polygonal scene to file */
  1016.   if (Option.write_result) {
  1017.     Create_Initial_ReceiverList(&RadScene);
  1018.     if (test_optik)
  1019.       Write_RadOptik(ReadLog, Option.OutSceneFilename,-1);
  1020.     else
  1021.       Write_Rad(ReadLog, Option.OutSceneFilename,-1);
  1022.   }
  1023.  
  1024.   /* Close table log */
  1025.   if (Option.tablelog == TRUE)
  1026.     LogRlog(0,"","");
  1027. }
  1028.